﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Prism.Mvvm;
using corpus_platform.Services;
using System.Collections.ObjectModel;
using Prism.Commands;
using corpus_platform.Data;
using Prism.Events;
using System.Diagnostics;
using Microsoft.Win32;
using System.IO;
using corpus_platform.Views;
using Prism.Services.Dialogs;
using System.Text.Json;
using System.Text.Encodings.Web;
using System.Text.Unicode;

namespace corpus_platform.ViewModels
{
    public partial class MainWindowViewModel : BindableBase
    {
        private Encoding articleEncode;

        private ISearchService<Frame> _frameworkSearchService;
        private ISearchService<Ontology> _ontologySearchService;
        private IEventAggregator _eventAggregator;
        //private IAnnotationMaintainService _annotationMaintainService;
        private ConfigManager _configManager;
        //private OntologyManager _ontologyManager;
        private IDialogService _dialogService;

        public MainWindowViewModel(ISearchService<Frame> frameworkSearchService,
            ISearchService<Ontology> ontologySearchService,
            //IAnnotationMaintainService annotationMaintainService,
            IEventAggregator eventAggregator,
            ConfigManager configManager,
            //OntologyManager ontologyManager,
            IDialogService dialogService)
        {
            _frameworkSearchService = frameworkSearchService;
            _ontologySearchService = ontologySearchService;
            //_annotationMaintainService = annotationMaintainService;
            _configManager = configManager;
            //_ontologyManager = ontologyManager;
            //_ontologyManager.connect(_configManager.OntologyDataPath);
            _dialogService = dialogService;

            _eventAggregator = eventAggregator;

            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            this.articleEncode = Encoding.GetEncoding(54936);
            if (!File.Exists(_configManager.FrameDataPath))
            {
                throw new Exception();
            }
            else
            {
                _frameworkSearchService.FilePath = _configManager.FrameDataPath;
                _frameworkSearchService.run();
            }
            if (!File.Exists(_configManager.OntologyDataPath))
            {
                throw new Exception();
            }
            else
            {
                _ontologySearchService.FilePath = _configManager.OntologyDataPath;
                _ontologySearchService.run();
            }
            if (!Directory.Exists(_configManager.AnnotationExchangeDir))
            {
                Directory.CreateDirectory(_configManager.AnnotationExchangeDir);
            }
        }

        private int articleEncodeIndex = 1;
        public int ArticleEncodeIndex
        {
            get { return articleEncodeIndex; }
            set {
                SetProperty(ref articleEncodeIndex, value);
                if (articleEncodeIndex == 0)
                {
                    this.articleEncode = Encoding.UTF8;
                }
                else
                {
                    this.articleEncode = Encoding.GetEncoding(54936);
                }
            }
        }

        private string article = "";
        public string Article
        {
            get { return article; }
            set { SetProperty(ref article, value); }
        }

        private string selectedText = "";
        public string SelectedText
        {
            get { return selectedText; }
            set { 
                SetProperty(ref selectedText, value); 
                if (!this.IsAnnotationBoxLocked)
                {
                    this.AnnotationText = this.SelectedText;
                }
            }
        }

        private string annotationText = "";
        public string AnnotationText
        {
            get { return annotationText; }
            set { SetProperty(ref annotationText, value); }
        }

        private string frameworkTerm = "";
        public string FrameworkTerm
        {
            get { return frameworkTerm; }
            set { SetProperty(ref frameworkTerm, value); }
        }

        private string ontologyTerm = "";
        public string OntologyTerm
        {
            get { return ontologyTerm; }
            set { SetProperty(ref ontologyTerm, value); }
        }

        private string selectedLexis;
        public string SelectedLexis
        {
            get { return selectedLexis; }
            set {
                SetProperty(ref selectedLexis, value);
                //CommandBindLexis.RaiseCanExecuteChanged();
            }
        }

        private int selectedLexisPosition;
        public int SelectedLexisPosition
        {
            get { return selectedLexisPosition; }
            set { SetProperty(ref selectedLexisPosition, value); }
        }

        private bool isAnnotationBoxLocked = false;
        public bool IsAnnotationBoxLocked
        {
            get { return isAnnotationBoxLocked; }
            set { SetProperty(ref isAnnotationBoxLocked, value); }
        }

        public RootViewModel Root { get; } = new();

        private DelegateCommand commandSearchFrameworks;
        public DelegateCommand CommandSearchFrameworks =>
            commandSearchFrameworks ?? (commandSearchFrameworks = new DelegateCommand(ExecuteCommandSearchFrameworks));

        void ExecuteCommandSearchFrameworks()
        {
            List<Frame> frames = _frameworkSearchService.search(FrameworkTerm, SearchMode.keyword);
            this.ListedFrames.Clear();
            foreach(Frame frame in frames)
            {
                this.ListedFrames.Add(new ListedFrame(frame, Root));
            }
            //_eventAggregator.GetEvent<StartAnnotationEvent>().Publish(IsAnnotationBoxLocked);
        }


        private DelegateCommand commandSearchOntologies;
        public DelegateCommand CommandSearchOntologies =>
            commandSearchOntologies ?? (commandSearchOntologies = new DelegateCommand(ExecuteCommandSearchOntologies));

        void ExecuteCommandSearchOntologies()
        {
            ListedOntologies.Clear();
            List<Ontology> ontologies = _ontologySearchService.search(OntologyTerm, SearchMode.keyword);
            foreach (Ontology ontology in ontologies)
            {
                this.ListedOntologies.Add(new ListedOntology(ontology, Root));
            }
            //_eventAggregator.GetEvent<StartAnnotationEvent>().Publish(IsAnnotationBoxLocked);
        }

        private DelegateCommand commandCreateFramework;
        public DelegateCommand CommandCreateFramework =>
            commandCreateFramework ?? (commandCreateFramework = new DelegateCommand(ExecuteCommandCreateFramework));

        void ExecuteCommandCreateFramework()
        {
        }

        private DelegateCommand commandCreateOntology;
        public DelegateCommand CommandCreateOntology =>
            commandCreateOntology ?? (commandCreateOntology = new DelegateCommand(ExecuteCommandCreateOntology));

        void ExecuteCommandCreateOntology()
        {
            DialogParameters parameters = new();
            //parameters.Add("ontologyManager", _ontologyManager);
            parameters.Add("eventAggregator", _eventAggregator);
            _dialogService.Show("ontologyEditer", parameters, (r) => { });
        }


        private DelegateCommand commandImportArticle;
        public DelegateCommand CommandImportArticle =>
            commandImportArticle ?? (commandImportArticle = new DelegateCommand(ExecuteCommandImportArticle));

        void ExecuteCommandImportArticle()
        {
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Multiselect = false;
            dlg.DefaultExt = ".txt";
            dlg.Filter = "文本文档|*.txt";
            bool? result = dlg.ShowDialog();

            if (result == true)
            {
                string filename = dlg.FileName;
                using (FileStream s = File.OpenRead(filename))
                using (TextReader reader = new StreamReader(s, this.articleEncode))
                {
                    this.Article = reader.ReadToEnd();
                }
            }
        }

        //private DelegateCommand commandBindLexis;
        //public DelegateCommand CommandBindLexis =>
        //    commandBindLexis ?? (commandBindLexis = new DelegateCommand(ExecuteCommandBindLexis, CanExecuteBindLexis));

        //void ExecuteCommandBindLexis()
        //{
        //    _annotationMaintainService.registLexis(SelectedBindingTreeNode, SelectedLexis, SelectedLexisPosition);
        //    _eventAggregator.GetEvent<LexisBindingChangedEvent>().Publish(SelectedBindingTreeNode.Id);
        //}

        //bool CanExecuteBindLexis()
        //{
        //    if(SelectedLexis != string.Empty && SelectedBindingTreeNode != null)
        //    {
        //        if (SelectedBindingTreeNode.Type == BindingTreeNodeType.ontology || SelectedBindingTreeNode.Type == BindingTreeNodeType.frameworkInstance)
        //        {
        //            return true;
        //        }
        //    }
        //    return false;
        //}

        private DelegateCommand commandStartAnnotation;
        public DelegateCommand CommandStartAnnotation =>
            commandStartAnnotation ?? (commandStartAnnotation = new DelegateCommand(ExecuteCommandStartAnnotation, CanExecuteCommandStartAnnotation));

        void ExecuteCommandStartAnnotation()
        {
            IsAnnotationBoxLocked = true;
            _eventAggregator.GetEvent<StartAnnotationEvent>().Publish(true);
            //_annotationMaintainService.registText(SelectedText);
        }

        bool CanExecuteCommandStartAnnotation()
        {
            return true;
        }

        private DelegateCommand commandEndAnnotation;
        public DelegateCommand CommandEndAnnotation =>
            commandEndAnnotation ?? (commandEndAnnotation = new DelegateCommand(ExecuteCommandEndAnnotation, CanExecuteCommandEndAnnotation));

        void ExecuteCommandEndAnnotation()
        {
            IsAnnotationBoxLocked = false;
            _eventAggregator.GetEvent<StartAnnotationEvent>().Publish(false);

            this.Root.Clear();
            //_annotationMaintainService.clearLexis();
            //_annotationMaintainService.clearText();
            //_annotationMaintainService.clearInstance();
        }

        bool CanExecuteCommandEndAnnotation()
        {
            return true;
        }

        private DelegateCommand commandSave;
        public DelegateCommand CommandSave =>
            commandSave ?? (commandSave = new DelegateCommand(ExecuteCommandSave, CanExecuteCommandSave));

        void ExecuteCommandSave()
        {
            DialogParameters dialogParameters = new()
            {
                {"corpus", this.SelectedText.Trim()}
            };

            _dialogService.Show("metaInformationConfirmWindow", dialogParameters, r =>
            {
                if (r.Result == ButtonResult.OK)
                {
                    MetaInformation metaInformation = r.Parameters.GetValue<MetaInformation>("metaInformation");
                    object value = this.Root.GetValue(metaInformation);
                    JsonSerializerOptions options = new JsonSerializerOptions()
                    {
                        Encoder = JavaScriptEncoder.Create(UnicodeRanges.All),
                        PropertyNamingPolicy = JsonNamingPolicy.CamelCase
                    };
                    string jsonString = JsonSerializer.Serialize(value, options);
                    File.WriteAllText(Path.Combine(_configManager.AnnotationExchangeDir, metaInformation.CorpusId + ".json"), jsonString, Encoding.GetEncoding(54936));
                }
            });
        }

        bool CanExecuteCommandSave()
        {
            return true;
        }
    }
}
